package middlewareWeb;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;

/**
 *Classe chemodellizza un proxy del worker che è delgato di comunicare con il Front end nella
 * gestione delle repliche
 * @author myusy
 */
public class WorkerProxyRM implements Observer{
    private BufferProxyRM bufferProxy;
    private Hashtable clocks = new Hashtable();
    /**
    *Metodo costruttore
     */
    public WorkerProxyRM(){
        this.bufferProxy = new BufferProxyRM();
        bufferProxy.addObserver(this);
    }
    /**
    *Metodo che restituisce il vector clock
     * @return HashTable (vector clock)
     */
    public Hashtable getClocks(){
        return this.clocks;
    }
    /**
    *Metodo override dell'interfaccia Observable per monitorare lo stato della coda
     *
     */
    @Override
    public synchronized void update(Observable o, Object arg) {
        InfoRM info = ((BufferProxyRM)o).getBuffer().elementAt(((InfoObserver)arg).getIndex());
        if (info != null) {
          
        boolean inserted = false;
        while (!inserted) {
            String vectorClock = enqueueFE(((InfoObserver)arg).getClocks().toString(),info.getComponentId(),info.getOperation(),info.getTask().getID(),info.getTask().getType().ordinal(),info.getAddress().getPort(),info.getAddress().getIp(),info.getTask().getCommand(),info.getTask().getLink());
            if (vectorClock.compareTo("")!=0) {
                inserted = true;
                Hashtable ricevuto = convert2Hashtable(vectorClock);
                clocks = max(ricevuto,clocks);
                clocks.put(info.getComponentId(), ((Integer)clocks.get(info.getComponentId()))+1);
            }
        }
        ((BufferProxyRM)o).getBuffer().elementAt(((InfoObserver)arg).getIndex()).setAckReceived(inserted);
        }
    }

    /**
    *Metodo
     * @return oggetto di tipo BufferProxyRM
     */
    public BufferProxyRM getBufferProxy(){
        return this.bufferProxy;
    }
    /**
    *Metodo che opera il confronto tra due vector clock e restituisce il nuovo vector clock che conterrà il
     * massimo valore per ogni componente del vettore
     * @return Hashtable vector clock
     */
    private Hashtable max(Hashtable ricevuto, Hashtable locale){
            Hashtable hash = new Hashtable();

            Enumeration e = ricevuto.keys();
            String key = new String();
            while(e.hasMoreElements()){
                key = (String)e.nextElement();
                if(key.compareTo("F001")!=0){
                    if(((Integer)ricevuto.get(key))<((Integer)locale.get(key)))
                        hash.put(key, locale.get(key));
                    else
                        hash.put(key, ricevuto.get(key));
                }else
                    hash.put(key, locale.get(key));
            }
            return hash;
    }
    /**
    *Metodo che opera l'operazione inversa del toString(), ricostruisce l'hashtable
     * a partire da una stringa
     * @param clock stringa da convertire
     * @return Hashtable vector clock
     */
    public Hashtable convert2Hashtable(String clock){
        Hashtable hash = new Hashtable();

        String c = clock.replace("{", "");
        c = c.replace("}", "");
        c = c.replace(" ", "");

        String s[] = c.split(",");
        String a[]= new String[2];

        for(int i = 0;i<s.length;i++) {
            a = s[i].split("=");
            hash.put(a[0], Integer.parseInt(a[1]));
        }
        return hash;
    }
    /**
    *Metodo che richiama un metodo del fornitore di servizi Front End
     */
    private static String enqueueFE(java.lang.String arg0, java.lang.String arg1, java.lang.String arg2, int arg3, java.lang.Integer arg4, int arg5, java.lang.String arg6, java.lang.String arg7, java.lang.String arg8) {
        clientWSFE.FrontEndService service = new clientWSFE.FrontEndService();
        clientWSFE.FrontEnd port = service.getFrontEndPort();
        return port.enqueueFE(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
    }

    
        
}
